当前位置:  开发笔记 > 编程语言 > 正文

`testl` eax对抗eax?

如何解决《`testl`eax对抗eax?》经验,为你挑选了5个好方法。

我想了解一些装配.

汇编如下,我对该testl行感兴趣:

000319df  8b4508        movl   0x08(%ebp), %eax  
000319e2  8b4004        movl   0x04(%eax), %eax  
000319e5  85c0          testl  %eax, %eax  
000319e7  7407          je     0x000319f0  

我想了解的那点testl之间的%eax%eax?我认为这段代码的具体内容并不重要,我只是试图用自己来理解测试 - 这种价值总是不正确吗?



1> 小智..:

意思test是将参数和AND组合在一起,并将结果检查为零.因此,此代码测试EAX是否为零.je如果为零,将跳跃.

顺便说一句,这会生成一个比cmp eax, 0编译器通常这样做的原因更小的指令.



2> Chris Jester..:

它测试eax是0,或更高,或更低.在这种情况下,如果eax为0 则跳转.


我进行了编辑,以将这个受欢迎的答案变成一个更好的规范答案,以暗示“这是TEST的全部内容,以及它与CMP有何不同”。有关同义的JE和JZ的语义含义的注释,请参阅我自己的答案。请检查我的修改内容,因为它相当大,仍然是您的答案。
哇,在编辑了我对这个问题的答案以包括我添加到你的内容后,我意识到我几乎完全复制了我在六月写的大部分内容.哎呀!我用更多的理由来更新它,以支持我的声明`test a,a`和`cmp $ 0,a` set flags相同; 谢谢你指出这是一个非平凡的主张.re:TEST vs.`test`:最近我开始使用英特尔手册等全部大写字母.但是,当我谈论AT&T助记符与英特尔助记符时,我使用`testb`样式进行AT&T.IDK,如果这有助于提高可读性.

3> Nils Pipenbr..:

测试指令在操作数之间执行逻辑AND操作,但不将结果写回寄存器.只更新标志.

在您的示例中,测试eax,如果eax为零,则eax将设置零标志,如果最高位设置则设置符号标志以及其他一些标志.

如果设置了零标志,则跳转如果等于(je)指令跳转.

您可以将代码转换为更易读的代码,如下所示:

cmp eax, 0
je  somewhere

它具有相同的功能,但需要一些字节更多的代码空间.这就是编译器发出测试而不是比较的原因.


对于零测试,它是完全有效的.
实际上,cmp可能无法在那里工作.也就是说,它适用于所呈现的特定情况,但cmp影响标志的方式与测试不同,因为它是内部子而不是和.要记住的事情.
但是你不知道以后还会看到哪些标志.对标志的影响是非常不同的,所以这可能是一个问题,而且经常是.
不,由不同的/方法/设置的唯一标志是进位和溢出,两者都设置为0.其他标志的/ values /将不同,因为cmp使用sub和test使用和.
@CodyBrocious:[`test eax,eax`](http://www.felixcloutier.com/x86/TEST.html)和[`cmp eax,0`](http://www.felixcloutier.com/x86/ CMP.html)都设置了所有标志,并将它们设置为相同的值.两条指令都"根据结果"设置所有标志.减去"0"永远不会产生进位或溢出.您的参数对于0以外的任何其他参数都是正确的,但不是0.

4> Peter Cordes..:

test就像and,除了它只写FLAGS,保持其输入不被修改.使用两个不同的输入,它可用于测试某些位是否全为零,或者是否设置了至少一个位.(例如,test al, 3如果EAX是4的倍数,则设置ZF(因此将其低2位归零).


test eax,eax将所有的标志正是以同样的方式cmp eax, 0:

CF和OF清除(AND/TEST总是那样;减去零从不产生进位)

根据EAX中的值,ZF,SF和PF.(a = a&a = a-0)

(除了过时的AF(辅助进位标志,由ASCII/BCD指令使用).TEST保留 未定义,但CMP"根据结果"设置它.由于减零不能产生从第4到第5的进位位,CMP应始终清除AF).


TEST更小(没有立即),有时更快(在比CMP更多的情况下,可以在更多CPU上宏 - 融合到比较和分支uop). 这使得test用于测试寄存器的优选习惯用于零.

使用CMP与即时0唯一的常见的原因是,当你想比较对内存操作数(例如,cmp reg,0在一个隐含的长度C风格字符串的结尾来检查结束零字节).


AVX512F增加了cmpb $0, (%esi) AVX512DQ/BW(Skylake但不是KNL)添加kortestw k1, k2,它在AVX512掩码寄存器(k0..k7)上运行,但仍然设置常规FLAGS,就像ktestb/w/d/q k1, k2整数testOR指令一样.

AND是基于AVX512比较结果分支/ cmovcc/setcc的惯用方法,取代了SSE/AVX2 ptest+ ucomisskortestw k1,k1.


使用(v)pmovmskb/ps/pdvs. test可能会令人困惑.

cmp并且jz字面上是相同的指令,即机器代码中的相同操作码. 他们做同样的事情,但对人类有不同的语义.反汇编程序(通常是编译器的asm输出)只会使用一个,因此语义上的区别就会丢失.

jejz在两个输入相等时设置ZF(即减法结果为0). je(如果相等则跳转)是语义相关的同义词.

cmp/ sub当结果为零时再次设置ZF,但没有"相等"测试.测试后的ZF没有告诉你两个操作数是否相等.所以je(如果为零则跳转)是语义相关的同义词.



5> DarenW..:

这段代码来自一个子程序,它被赋予一个指向某事物的指针,可能是一些结构或对象.第二行取消引用指针,从该东西获取一个值 - 可能本身就是一个指针,或者只是一个int,存储为第二个成员(偏移+4).第3行和第4行将此值测试为零(如果它是指针则为NULL),如果为零,则跳过以下几个操作(未显示).

对零的测试有时被编码为与直接的文字零值进行比较,但编写此文件的编译器(或人?)可能认为测试操作会运行得更快 - 考虑所有现代CPU的东西,如流水线和寄存器重命名.它来自同一个技巧包含清除XOR EAX,EAX(我在科罗拉多州某人的车牌上看到的)登记册的想法,而不是明显但可能更慢的MOV EAX,#0(我使用较旧的表示法) ).

在asm中,像perl,TMTOWTDI.

推荐阅读
Gbom2402851125
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有